package com.lzy.admin.controller;

import com.github.pagehelper.Page;
import com.lzy.admin.service.AdminUserService;
import com.lzy.api.controller.admin.AdminMngControllerApi;
import com.lzy.api.controller.user.BaseController;
import com.lzy.exception.GraceException;
import com.lzy.grace.result.GraceJSONResult;
import com.lzy.grace.result.ResponseStatusEnum;
import com.lzy.pojo.AdminUser;
import com.lzy.pojo.bo.AdminLoginBO;
import com.lzy.pojo.bo.NewAdminBO;
import com.lzy.utils.FaceVerifyUtils;
import com.lzy.utils.PagedGridResult;
import com.lzy.utils.extend.TecentResource;
import com.tencentcloudapi.common.Credential;
import org.apache.catalina.connector.Response;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.util.StringUtil;
import com.tencentcloudapi.common.AbstractModel;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;

@RestController
public class AdminMngController extends BaseController implements AdminMngControllerApi {

    final static Logger logger = LoggerFactory.getLogger(AdminMngController.class);

    @Autowired
    private AdminUserService adminUserService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private TecentResource tecentResource;

    @Override
    public GraceJSONResult adminLogin(AdminLoginBO adminLoginBO,
                                      HttpServletRequest request,
                                      HttpServletResponse response,
                                      BindingResult result) {

        //1. 如果非人脸登录，判断BindingResult是否保存错误的验证信息，如果有，则直接return
        if(StringUtils.isBlank(adminLoginBO.getImg64())){
            if (result.hasErrors()) {
                Map<String, String> errorMap = getErrors(result);
                return GraceJSONResult.errorMap(errorMap);
            }
        }


        //2. 查询admin用户的信息
        AdminUser adminUser = adminUserService.queryAdminByUsername(adminLoginBO.getUsername());

        //3. 判断admin是否存在，如果不存在则登录失败
        if(adminUser == null){
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_NOT_EXIT_ERROR);
        }

        //4. 判断输入的密码和数据库存储的密码是否一致
        Boolean isPwdMatch =  BCrypt.checkpw(adminLoginBO.getPassword(),adminUser.getPassword());
        if(isPwdMatch){
            doLoginSettings(adminUser,request,response);
            return GraceJSONResult.ok();
        }else{
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_NOT_EXIT_ERROR);
        }
    }

    @Override
    public GraceJSONResult adminIsExist(String username) {
        checkAdminExist(username);
        return GraceJSONResult.ok();
    }

    @Override
    public GraceJSONResult addNewAdmin(NewAdminBO newAdminBO, HttpServletRequest request, HttpServletResponse response) {

        // 1. base64不为空，则代表人脸入库，否则需要管理员输入密码和确认密码
        if(StringUtils.isBlank(newAdminBO.getImg64())){
            if(StringUtils.isBlank(newAdminBO.getPassword()) ||
              StringUtils.isBlank(newAdminBO.getConfirmPassword())){
                return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_PASSWORD_ERROR);
            }
        }
        // 2. 密码不为空，则必须两次输入一致
        if(StringUtils.isNotBlank(newAdminBO.getPassword())){
            if(!newAdminBO.getPassword().equalsIgnoreCase(newAdminBO.getConfirmPassword())){
                return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_PASSWORD_ERROR);
            }
        }

        // 3. 校验用户名唯一
        checkAdminExist(newAdminBO.getUsername());

        // 4. 调用service层，添加管理员
        adminUserService.createAdminUser(newAdminBO);
        return GraceJSONResult.ok();
    }

    @Override
    public GraceJSONResult getAdminList(Integer page, Integer pageSize) {
        if(page == null){
            page = COMMON_START_PAGE;
        }
        if(pageSize == null){
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = adminUserService.queryAdminList(page,pageSize);

        return GraceJSONResult.ok(gridResult);
    }

    @Override
    public GraceJSONResult adminLogOut(String adminId, HttpServletRequest request, HttpServletResponse response) {

        // 1. 从redis中删除会话token
        redis.del(REDIS_ADMIN_TOKEN + ":" + adminId);

        // 2. 删除cokkie信息
        deleteCookie(request,response,"atoken");
        deleteCookie(request,response,"aid");
        deleteCookie(request,response,"aname");

        return GraceJSONResult.ok();
    }

    @Override
    public GraceJSONResult adminFaceLogin(AdminLoginBO adminLoginBO,
                                          HttpServletRequest request,
                                          HttpServletResponse response) {

        // 1. 判断用户名和人脸信息不能为空
        if(StringUtils.isBlank(adminLoginBO.getUsername())){
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_USERNAME_NULL_ERROR);
        }

        String tempFace64 = adminLoginBO.getImg64();
        if(StringUtils.isBlank(tempFace64)){
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_FACE_NULL_ERROR);
        }

        // 2. 从数据库中查询出faceId
        AdminUser adminUser = adminUserService.queryAdminByUsername(adminLoginBO.getUsername());

        String adminFaceId = adminUser.getFaceId();
        System.out.println(adminFaceId);
        // 3. 请求文件服务,获取人脸数据的base64数据
        if(StringUtils.isBlank(adminFaceId)){
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_FACE_LOGIN_ERROR);
        }
        String fileServeUrlExecute = "http://files.lzynews.com:8004/fs/readFace64InGridFs?faceId=" + adminFaceId;
        ResponseEntity<GraceJSONResult> responseEntity =  restTemplate.getForEntity(fileServeUrlExecute,GraceJSONResult.class);
        GraceJSONResult bodyResult = responseEntity.getBody();
        String base64DB = (String)bodyResult.getData();

        // 4. 调用腾讯云ai进行人脸对比识别，判断可信度，从而实现登录
        if(!faceVerify(tempFace64,base64DB,90)){
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ADMIN_FACE_LOGIN_ERROR);
        }

        // 5. admin登录后的数据设置，redis和cookie
        doLoginSettings(adminUser,request,response);
        return GraceJSONResult.ok();
    }


    /**
    * @Author lzy
    * @Description This is description of method
    * @Param adminUser
    * @Param request
    * @Param response
    * @Since version 1.0
    */
    private void doLoginSettings(AdminUser adminUser,
                                 HttpServletRequest request,
                                 HttpServletResponse response){

        // 1.保存token放入到redis中
        String token = UUID.randomUUID().toString();
        redis.set(REDIS_ADMIN_TOKEN + ":" + adminUser.getId(),token);

        // 2.设置cokkie
        setCookie(request, response, "atoken", token, COOKIE_MONTH);
        setCookie(request, response, "aid",adminUser.getId(), COOKIE_MONTH);
        setCookie(request, response, "aname",adminUser.getAdminName(), COOKIE_MONTH);
    }

    private void checkAdminExist(String username){
        AdminUser adminUser = adminUserService.queryAdminByUsername(username);

        if(adminUser != null){
            GraceException.display(ResponseStatusEnum.ADMIN_USERNAME_EXIST_ERROR);
        }
    }


    private boolean faceVerify(String base641,String base642,Integer targetConfidence){
        try{
            Credential cred = new Credential(tecentResource.getSecretId(), tecentResource.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, "ap-beijing", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            CompareFaceRequest req = new CompareFaceRequest();
            req.setImageA(base641);
            req.setImageB(base642);
            // 返回的resp是一个CompareFaceResponse的实例，与请求对象对应
            CompareFaceResponse resp = client.CompareFace(req);
            System.out.println(resp.getScore());
            if(resp.getScore() < targetConfidence){
                return false;
            }
            // 输出json格式的字符串回包
            System.out.println(AbstractModel.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
        return true;
    }

}
